package controller;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import view.SpelbordView;
import model.Spel;
import model.Tegel;

public class Controller {
	
	private static Controller instance;
	private Spel spel;
	private SpelbordView spelbordView;
	public static int defaultAantalTegels = 8;
	private Context context;

	/**
	 * Maakt een nieuwe Controller aan die spel instantie heeft
	 */
	private Controller(Context context) {
		this.context = context;
		int aantalTegels = getAantalTegels();
		//geef het aantal tegels mee aan het spel
		spel = new Spel(aantalTegels);
	}
	/**
	 * Get aantal tegels van de preferences
	 * @return
	 */
	private int getAantalTegels() {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
	    return sharedPrefs.getInt("aantaltegelspref", defaultAantalTegels);
	}

	/**
	 * Get instantie van Controller, altijd maar een (singleton)
	 * @return
	 */
	public static Controller getInstance() {
		return instance;
	}
	/**
	 * Get instantie van Controller, altijd maar een (singleton)
	 * @return
	 */
	public static Controller getInstance(Context context) {
		if (instance == null) instance = new Controller(context);
		return getInstance();
	}

	/**
	 * Opnieuw spelen door een nieuw spel sessie te starten
	 */
	public void opnieuwSpelen(Context context) {
		spel.startNewSpelSessie(context);
		spelbordView.resetAantalZettenTekst();
		spelbordView.refreshGridView();
	}
	
	/**
	 * Handel de geklikte tegel (zet) af
	 * @param tegel
	 * @param position van de tegel in de array
	 */
	public void afhandelZet(int position) {
		Tegel tegel = spel.getTegel(position); 

		//dit is de eerste tegel die opengedraaid is, geen check nodig
		if (!isOpenEersteTegel()) {
			spel.getHuidigeSpelSessie().setVorigeTegel(tegel, position);
			return;
		}
		//de geklikte tegel mag niet op geklikt worden
		if (!valideerTegel(position)) {
			return;
		}
		
		//*******************************************************************
		//VALIDATIES
		//
		//Kijkt of de geopende tegels hetzelfde zijn
		boolean match = checkTegelsMatch(position);
		
		//if match, update gevonden properties
		if (match) {
			 Controller.getInstance().setGevondenTegels(position);
			 checkEindeSpel();
		//anders de tegels sluiten
		} else {
			Tegel vorigeTegel = spel.getHuidigeSpelSessie().getVorigeTegel();
			int vorigeTegelPos = spel.getHuidigeSpelSessie().getVorigeTegelPos();
			spelbordView.handler.postDelayed(new ShowAchterkantTegels(vorigeTegel, vorigeTegelPos, tegel, position), 1000);
		}
		//*******************************************************************
		//UPDDATE spel variabelen
		//update aantal zetten 
		spel.getHuidigeSpelSessie().addZet();
		
		//reset vorige tegel
		spel.getHuidigeSpelSessie().resetVorigeTegel();
	}

	/**
	 * Check of het spel einde heeft bereikt
	 */
	private void checkEindeSpel() {
		spel.checkEindeSpel();
	}
	
	/**
	 * Check of bij deze poging al een tegel open is gedraaid
	 * @return
	 */
	public boolean isOpenEersteTegel() {
		return (spel.getHuidigeSpelSessie().getVorigeTegel() != null) ? true : false;
	}
	/**
	 * Toont de tegel door property setZichtbaar op true en gridView te refreshen
	 * @param position
	 */
	public void setZichtbaarTegel(int position) {
		Tegel tegel = spel.getTegel(position);
		if (!tegel.isZichtbaar()) {
			tegel.setZichtbaar(true);
			spel.setTegel(tegel, position);
		}
	}
	
	/**
	 * De waardes van gevonden op true zetten bij de matchende tegels
	 * @param position van de geklikte tegel
	 */
	private void setGevondenTegels(int position) {
		Tegel tegel = spel.getTegel(position);
		spel.setGevondenTegels(tegel, position);
	}
	
	/**
	 * Kijk of de geklikte tegel geklikt mag worden
	 * @param index
	 * @return
	 */
	private boolean valideerTegel(int index) {
		boolean geldigeActie = true;
		
		Tegel tegel = spel.getTegel(index);
		int vorigeTegelPos = spel.getHuidigeSpelSessie().getVorigeTegelPos();
		
		//op dezelfde tegel geklikt door de positie te checken
		if (index == vorigeTegelPos) {
			geldigeActie = false;
		}
		
		if (tegel.isGevonden()) {
			geldigeActie = false;
		}
		
		return geldigeActie;
	}
	
	/**
	 * Kijkt of de tegels matchen, door het spel zelf laten checken
	 * @param position
	 * @return
	 */
	private boolean checkTegelsMatch(int position) {
		Tegel tegel = spel.getTegel(position);
		return spel.getHuidigeSpelSessie().checkTegelsMatch(tegel);
	}

	//*************************************************************
	//Getters en setters
	//
	//*************************************************************
	/** 
	 * Geeft terug spel
	 * @return
	 */
	public Spel getSpel() {
		return spel;
	}
	/**
	 * Get spelbord view
	 * @return
	 */
	public SpelbordView getSpelbordView() {
		return spelbordView;
	}
	/**
	 * Set spelbord view
	 * @param spelbordView
	 */
	public void setSpelbordView(SpelbordView spelbordView) {
		this.spelbordView = spelbordView;
	}
	/**
	 * Set spel
	 * @param spel
	 */
	public void setSpel(Spel spel) {
		this.spel = spel;
	}
	/**
	 * Set de context
	 * @param context
	 */
	public void setContext(Context context) {
		this.context = context;
	}
	/**
	 * Get de context
	 * @return
	 */
	public Context getContext() {
		return context;
	}
	//**************************************************************
	/**
	 * Handler om de tegels om te draaien door de zichtbaarheid op false te zetten
	 */
	protected class ShowAchterkantTegels implements Runnable {
		Tegel eersteTegel, tweedeTegel;
		int eersteTegelPos, tweedeTegelPos;
		
		ShowAchterkantTegels(Tegel eersteTegel, int eersteTegelPos, Tegel tweedeTegel, int tweedeTegelPos) {
			this.eersteTegel = eersteTegel;
			this.tweedeTegel = tweedeTegel;
			this.eersteTegelPos = eersteTegelPos;
			this.tweedeTegelPos = tweedeTegelPos;
		}
		
		public void run() {
			eersteTegel.setZichtbaar(false);
			tweedeTegel.setZichtbaar(false);
			Controller.getInstance().getSpel().setTegel(eersteTegel, eersteTegelPos);
			Controller.getInstance().getSpel().setTegel(tweedeTegel, tweedeTegelPos);
			spelbordView.refreshGridView();
		}
	}
}
